using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.Drawing;
using System.Globalization;

namespace Camalon.Drawing
{
    /// <summary>
    /// The CompoundColor represents a color with a starting position within a <see cref="MulticolorFill"/> 
    /// or <see cref="ShapePen"/> object./>
    /// </summary>
    /// <example>
    /// LinearGradientFill fill = new LinearGradientFill( );
    /// //Green color starts on the left side (0% = 0F) of the shapes boundary
    /// //Aqua color is 50 percent (=0.5F) of the way from the left side of the shape's boundary.
    /// //Blue color ends on the right side (100% = 1F) of the shapes boundary
    /// 
    ///fill.InterpolationColors = new CompoundColor[]
    ///{
    ///     new CompoundColor(System.Drawing.Color.Green, 0F),
    ///     new CompoundColor(System.Drawing.Color.Aqua, 0.25F),
    ///     new CompoundColor(System.Drawing.Color.Blue, 1F)
    ///};
    /// </example>
	[Serializable]
	[TypeConverter(typeof(CompoundColorConverter))]
    [Editor("Camalon.Drawing.Design.TransparentColorEditor, Camalon.Drawing.Design", typeof(System.Drawing.Design.UITypeEditor))]
    public struct CompoundColor
	{
		private Color _color;

		private float	_compoundValue;

		public CompoundColor(Color color, float compoundValue)
		{
			_color = color;
			_compoundValue = compoundValue;
		}

        /// <summary>
        /// Initializes a new instance of the <see cref="CompoundColor"/> struct.
        /// </summary>
        /// <param name="color">The color.</param>
		public CompoundColor(Color color)
		{
			_color = color;
			_compoundValue = 0f;
		}

        /// <summary>
        /// Gets or sets the compound value. 
        /// </summary>
        /// <value>The compound value.</value>
        /// <remarks>Only valid, when used in a multicolor ShapeFill or a ShapePen object.</remarks>
		[DefaultValue(0.0f)]
		[RefreshProperties( RefreshProperties.Repaint)]
		[Description("A value between 0% and 100%. Only valid, when used in a multicolor ShapeFill or a ShapePen object.")]
		[TypeConverter(typeof(RoundedPercentConverter))]
		public float CompoundValue
		{
			get{ return _compoundValue;} 
			set
			{ 
				if( value == _compoundValue ) return;

				if( value < 0.0f ) value = 0.0f;
				if( value > 1.0f ) value = 1.0f;

				_compoundValue = value;
			}
		}


        /// <summary>
        /// Gets or sets the color.
        /// </summary>
        /// <value>The color.</value>
		[Description("Base color value")]
		[Browsable(true)]
		[TypeConverter(typeof(ExtendedColorConverter))]
		[DefaultValue( typeof( Color), "Empty")]
        [Editor("Camalon.Drawing.Design.TransparentColorEditor, Camalon.Drawing.Design", typeof(System.Drawing.Design.UITypeEditor))]
        public Color Color
		{
			get{ return _color;}
			set{_color = value;}

		}

        /// <summary>
        /// Gets the color transparency.
        /// </summary>
        /// <value>The transparency.</value>
		[DefaultValue(0.0f)]
		[RefreshProperties( RefreshProperties.Repaint)]
		[TypeConverter(typeof(RoundedPercentConverter))]
		[Description("Transparency value of color values range from 0% (totally opaque) to 100% (totally transparent).")]
		public float Transparency
		{
			get	{	return TransparentColor.GetTransparency( _color.A ); }
		}

        /// <summary>
        /// Gets a value indicating whether this instance is empty.
        /// </summary>
        /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
		[Browsable( false )]
		[Description ( "Indicates empty color.")] 
		public bool IsEmpty
		{
			get
			{
				return _color.IsEmpty;// _color.A ==0 && _color.R==0 && _color.G == 0 && _color.B==0;// == Color.Empty;
			}
		}

        /// <summary>
        /// Gets a value indicating whether this instance is transparent.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is transparent; otherwise, <c>false</c>.
        /// </value>
		[Browsable( false )]
		[Description ( "Indicates totally transparent color.")] 
		public bool IsTransparent
		{
			get
			{
				return !IsEmpty && _color.A == 0;
			}
		}


        /// <summary>
        /// Gets an empty compound color.
        /// </summary>
        /// <value>The empty.</value>
		public static CompoundColor Empty
		{
			get
			{
				return new CompoundColor( System.Drawing.Color.Empty, 0f);
			}
		}

        /// <summary>
        /// Gets a transparent compound color.
        /// </summary>
        /// <value>The transparent.</value>
		public static CompoundColor Transparent
		{
			get
			{
				return new CompoundColor( System.Drawing.Color.Transparent );
			}
		}

        /// <summary>
        /// Indicates empty or totally transparent color.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is empty or totally transparent; otherwise, <c>false</c>.
        /// </value>
		[Browsable( false )]
		[Description ( "Indicates empty or totally transparent color.")] 
		public bool IsVisible
		{
			get{ return !IsEmpty && !IsTransparent;}

		}




		#region overrides
		public override bool Equals(object obj)
		{
			if(!( obj is CompoundColor)) return false;
			return this == (CompoundColor)obj;
		}

		public bool Equals(CompoundColor tranparentColor)
		{
			return _color == tranparentColor.Color;
		}

		public override int GetHashCode()
		{
			return _color.GetHashCode() ^ _compoundValue.GetHashCode();
		}
		#endregion overrides 

		#region operators
		public static bool operator ==(	CompoundColor color1,CompoundColor color2	)
		{
			return color1._color == color2._color && color1._compoundValue == color2._compoundValue;
		}

		public static bool operator !=(	CompoundColor color1,CompoundColor color2	)
		{
			return !(color1 == color2);
		}

		public static implicit operator CompoundColor(	Color color )
		{
			return new CompoundColor(color);
		}

		public static implicit operator Color(	CompoundColor compoundColor )
		{
			return compoundColor.Color;
		}

		public static implicit operator CompoundColor(	TransparentColor color )
		{
			return new CompoundColor(color);
		}

		public static implicit operator TransparentColor(	CompoundColor compoundColor )
		{
			return compoundColor.Color;
		}

		#endregion 


	}
}
